#include "../mqserver/routing.hpp"
#include <gtest/gtest.h>

class RoutingTest : public testing::Environment
{
    virtual void SetUp() override
    {
    }

    virtual void TearDown() override
    {
    }
};

TEST(routingtest, rkey_legal_test)
{
    ASSERT_EQ(mmq::Routing::IsLegalRoutingKey("news.music.pop"), true);
    ASSERT_EQ(mmq::Routing::IsLegalRoutingKey("news..music.pop"), true);
    ASSERT_EQ(mmq::Routing::IsLegalRoutingKey("news.,music.pop"), false);
    ASSERT_EQ(mmq::Routing::IsLegalRoutingKey("news.music_123.pop"), true);
}

TEST(routingtest, bkey_legal_test)
{
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.music.pop"), true);
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.#.music.pop"), true);
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.#.*.music.pop"), false);
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.*.#.music.pop"), false);
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.#.#.music.pop"), false);
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.*.*.music.pop"), true);
    ASSERT_EQ(mmq::Routing::IsLegalBindingKey("news.,music_123.pop"), false);
}

TEST(routingtest, route_test)
{
    // [测试⽤例]
    // binding key      routing key             result
    // aaa              aaa                     true
    // aaa.bbb          aaa.bbb                 true
    // aaa.bbb          aaa.bbb.ccc             false
    // aaa.bbb          aaa.ccc                 false
    // aaa.#.bbb        aaa.bbb.ccc             false
    // aaa.bbb.#        aaa.ccc.bbb             false
    // #.bbb.ccc        aaa.bbb.ccc.ddd         false
    // aaa.bbb.ccc      aaa.bbb.ccc             true
    // aaa.*            aaa.bbb                 true
    // aaa.*.bbb        aaa.bbb.ccc             false
    // *.aaa.bbb        aaa.bbb                 false
    // #                aaa.bbb.ccc             true
    // aaa.#            aaa.bbb                 true
    // aaa.#            aaa.bbb.ccc             true
    // aaa.#.ccc        aaa.ccc                 true
    // aaa.#.ccc        aaa.bbb.ccc             true
    // aaa.#.ccc        aaa.aaa.bbb.ccc         true
    // #.ccc            ccc                     true
    // #.ccc            aaa.bbb.ccc             true
    // aaa.#.ccc.ccc    aaa.bbb.ccc.ccc.ccc     true
    // aaa.#.bbb.*.bbb  aaa.ddd.ccc.bbb.eee.bbb true

    std::vector<std::string> bkeys = {
        "aaa",
        "aaa.bbb",
        "aaa.bbb",
        "aaa.bbb",
        "aaa.#.bbb",
        "aaa.bbb.#",
        "#.bbb.ccc",
        "aaa.bbb.ccc",
        "aaa.*",
        "aaa.*.bbb",
        "*.aaa.bbb",
        "#",
        "aaa.#",
        "aaa.#",
        "aaa.#.ccc",
        "aaa.#.ccc",
        "aaa.#.ccc",
        "#.ccc",
        "#.ccc",
        "aaa.#.ccc.ccc",
        "aaa.#.bbb.*.bbb"
    };
    std::vector<std::string> rkeys = {
        "aaa",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.ccc",
        "aaa.bbb.ccc",
        "aaa.ccc.bbb",
        "aaa.bbb.ccc.ddd",
        "aaa.bbb.ccc",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.ccc",
        "aaa.bbb.ccc",
        "aaa.aaa.bbb.ccc",
        "ccc",
        "aaa.bbb.ccc",
        "aaa.bbb.ccc.ccc.ccc",
        "aaa.ddd.ccc.bbb.eee.bbb"
    };
    std::vector<bool> result = {
        true,
        true,
        false,
        false,
        false,
        false,
        false,
        true,
        true,
        false,
        false,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true
    };
    for(int i = 0; i < result.size(); i++)
    {
        ASSERT_EQ(mmq::Routing::Route(mmq::ExchangeType::TOPIC, rkeys[i], bkeys[i]), result[i]);
    }
}

int main(int argc, char *argv[])
{
    testing::InitGoogleTest(&argc, argv);
    testing::AddGlobalTestEnvironment(new RoutingTest);
    int ret = RUN_ALL_TESTS();
}